home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / ab20_archive / utilities / shells / csh519s.lha / comm3.c < prev    next >
C/C++ Source or Header  |  1992-02-24  |  33KB  |  1,731 lines

  1. /*
  2.  * COMM3.C
  3.  *
  4.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  5.  * Version 5.00L by Urban Mueller 17-Feb-91
  6.  *
  7.  */
  8.  
  9. #include "shell.h"
  10.  
  11. /* comm3.c */
  12. static void doassign(char *log, char *phy);
  13. static void assignlist(void);
  14. static int strings_in_file(long mask, char *s, char *path);
  15. static int htype_a_file   (long mask, char *s, char *path);
  16. static void install_menu(char **mav, int mac);
  17. static int line_filter( char *(*line)(char *) );
  18.  
  19.  
  20. do_tee( void )
  21. {
  22.     char buf[256];
  23.     FILE *out;
  24.  
  25.     prepscroll( ac==1 );
  26.     if( ac>2 ) { ierror( av[2], 500 ); return 20; }
  27.     if( ac==1 ) out=stderr;
  28.     else if( !(out=fopen( av[1], "w" ))) { pError( av[1] ); return 20; }
  29.     while (safegets(buf,stdin)) {
  30.         puts(buf);
  31.         quickscroll();
  32.         fprintf(out,"%s\n",buf);
  33.     }
  34.     if( ac!=1 ) fclose( out );
  35.     return 0;
  36. }
  37.  
  38. do_head( char *garbage, int com )
  39. {
  40.     int i, n;
  41.     FILE *f;
  42.     char buf[256];
  43.  
  44.     if (ac>2) {
  45.         n=(int)(long)Atol(av[2]);
  46.         if (IoErr()) {
  47.             ierror(av[2],511);
  48.             return 20;
  49.         }
  50.     } else n=10;
  51.  
  52.     f=fopen(av[1], "r");
  53.     if (f==NULL) {
  54.         pError(av[1]);
  55.         return 20;
  56.     }
  57.     if (com) {    /* tail specific part */
  58.         i=0;
  59.         while (fgets(buf, 256, f) && ! dobreak()) i++;
  60.         rewind(f);
  61.         if (n>i) n=i;
  62.         i=i-n;
  63.         while (i-- && fgets(buf, 256, f) && ! dobreak()) ;
  64.     }
  65.     for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++)
  66.         printf("%s", buf);
  67.     fclose(f);
  68.     return 0;
  69. }
  70.  
  71. static int
  72. exword( char **src, char *buf )
  73. {
  74.     *buf=0;
  75.     if( **src==0 ) return 0;
  76.     while( **src && **src!=0xA0 )
  77.         *buf++=*(*src)++;
  78.     *buf=0;
  79.     if( **src ) (*src)++;
  80.     return 1;
  81. }
  82.  
  83. static char helpfound=0;
  84.  
  85. void
  86. man (FILE *f, char *s)
  87. {
  88.     char buf[140], entry[100];
  89.     int  len = sprintf (entry, "    %s", s);
  90.     char *example = "    ";
  91.  
  92.     prepscroll (0);
  93.     rewind (f);
  94.     do {                        /* look for required argument */
  95.         if (fgets (buf, sizeof(buf), f)==NULL || dobreak())
  96.             return;                /* GMD */
  97.     } while (Strncmp (entry, buf, len)) ;
  98.     helpfound = 1;
  99.  
  100.     do {                /* display help */
  101.         if (dobreak())
  102.             return;
  103.         quickscroll ();
  104.         printf ("%s", buf);
  105.         if (fgets (buf, sizeof(buf), f) == NULL)
  106.             return;
  107.     } while ((!isalphanum (*buf)) && strncmp (buf, example, strlen(example))) ;
  108. }
  109.  
  110.  
  111. do_man( void )
  112. {
  113.     FILE *f;
  114.     int i;
  115.     char buf[200], name[60], *src, *var, docfound=0;
  116.  
  117.     buf[0]=0;
  118.     if( var=get_var(LEVEL_SET,"_man" ) )
  119.         strcpy(buf,var);
  120.  
  121.     if (ac==1) ac=2, av[1]="MAN";
  122.     for (i=1; i<ac; i++) {
  123.         src=buf, helpfound=0;
  124.         while( exword( &src, name) )
  125.             if( f=fopen(name, "r") ) {
  126.                 docfound=1;
  127.                 man(f, av[i]);
  128.                 fclose(f);
  129.                 if( helpfound )
  130.                     break;
  131.             }
  132.         if( !docfound )
  133.             fprintf(stderr,"%s not found\n",buf);
  134.         else if( !helpfound )
  135.             fprintf(stderr, "Help not found for %s\n", av[i]);
  136.     }
  137.     return 0;
  138. }
  139.  
  140. do_assign( void )
  141. {
  142.     int i;
  143.  
  144.     if     (  ac==1  ) assignlist();
  145.     else if(  ac==2  ) doassign(av[1], NULL);
  146.     else if( !(ac&1) ) ierror(NULL, 500);
  147.     else
  148.         for( i=1; i<ac; i+=2 )
  149.             doassign( av[i],av[i+1] );
  150.     return 0;
  151. }
  152.  
  153. static char *assign_errors[4]={
  154.     "",
  155.     "Name %s is not valid\n",
  156.     "Weird error\n",
  157.     "Can't cancel %s:\n"
  158.     };
  159.  
  160.  
  161. static void
  162. doassign(char *log, char *phy)
  163. {
  164.     int last=strlen(log) - 1;
  165.  
  166.     if (log[last] != ':') fprintf(stderr, "Bad name %s\n", log);
  167.     else {
  168.         log[last] = 0;
  169. #ifdef KICK20
  170.         if( options && phy && o_kick20 ) {
  171.             BPTR lock;
  172.             int succ=0;
  173.             if     ( options&1 ) succ=AssignLate( (UBYTE*)log,(UBYTE*)phy );
  174.             else if( options&2 ) succ=AssignPath( (UBYTE*)log,(UBYTE*)phy );
  175.             else if( options&4 )
  176.                 if( lock=Lock(phy,ACCESS_READ) )
  177.                     if( !(succ=AssignAdd((UBYTE *)log,lock)))
  178.                         UnLock(lock);
  179.             if( !succ )
  180.                 pError( log );
  181.         } else 
  182. #endif
  183.                if( !(options&4) ) {
  184.             int err=Assign(log, phy);
  185.             fprintf(stderr,assign_errors[err],err==1?phy:log);
  186.         }
  187.     }
  188. }
  189.  
  190. extern struct RootNode2x *RootNode;
  191. #define ENTRIES 128
  192.  
  193. static void
  194. assignlist()
  195. {
  196.     char *ptr, *log, **arr;
  197.     int ctr, i;
  198.  
  199.     if(!(arr=expand_devs()))
  200.         return;
  201.  
  202.     printf("Devices:\n");
  203.     for (i=ctr=0; arr[i] && *arr[i]==1; i++) {
  204.         printf("%-8s",arr[i]+1);
  205.         if (ctr++ == 5) { ctr=0; printf("\n"); }
  206.     }
  207.  
  208.     printf("\n\nVolumes:\n");
  209.     for( ; arr[i] && *arr[i]==2; i++ )
  210.         printf( "%-16s [Mounted]\n",arr[i]+1);
  211.  
  212.     printf("\nDirectories:\n");
  213.     for( ; arr[i] && !dobreak(); i++ ) {
  214.         log=arr[i]+1; ptr=log+strlen(log)+1;
  215.         switch( *(log-1)) {
  216.         case 3:
  217.             printf("%-20s%s\n", log, ptr);
  218.             for(;;) {
  219.                 ptr+=strlen(ptr)+1;
  220.                 if( !*ptr ) break;
  221.                     printf("%-19s+%s\n", "", ptr);
  222.             }
  223.             break;
  224.         case 4: printf("%-20s<%s>\n", log, ptr); break;
  225.         case 5: printf("%-20s[%s]\n", log, ptr); break;
  226.         }
  227.     }
  228.  
  229.     free_expand( arr );
  230. }
  231.  
  232. char **
  233. expand_devs(void)
  234. {
  235.     static char Type[]={1,3,2,4,5};
  236.     struct DosInfo *info=(void*)((long)RootNode->rn_Info*4);
  237.     struct DosList2x *list=(void*)((long) info->di_DevInfo*4);
  238.     struct AssignList2x *path;
  239.     char buf[256], **arr, *ptr;
  240.     int n;
  241.  
  242.     if( !(arr=malloc(ENTRIES*sizeof(char *))))
  243.         return NULL;
  244.  
  245.     Forbid();
  246.     for( n=0; list && n<ENTRIES; list=(void*)((long)list->dol_Next*4)) {
  247.         if( list->dol_Type<0 || list->dol_Type>DLST_NONBINDING )
  248.             continue;
  249.         ptr=buf;
  250.         *ptr++=Type[list->dol_Type];
  251.         ptr+=BtoCStr(ptr,list->dol_Name,200);
  252.         *ptr++=':'; *ptr++=0;
  253.         switch( list->dol_Type) {
  254.         case DLST_DIRECTORY : 
  255.             if(list->dol_Lock)
  256.                 PathName(list->dol_Lock, ptr, 200);
  257.             else 
  258.                 strcpy(ptr,"Nonexisting lock");
  259.             ptr+=strlen(ptr)+1;
  260.             if( o_kick20 ) {
  261.                 path=(void*)list->dol_misc.dol_assign.dol_List;
  262.                 for( ; o_kick20 && path; path=(void*)path->al_Next ) {
  263.                     if(list->dol_Lock)
  264.                         PathName(path->al_Lock, ptr, 200);
  265.                     else 
  266.                         strcpy(ptr,"Nonexisting lock");
  267.                     ptr+=strlen(ptr)+1;
  268.                 }
  269.             }
  270.             *ptr++=0;
  271.             break;
  272.         case DLST_LATE      : 
  273.         case DLST_NONBINDING:
  274.             ptr+= sprintf(ptr,"%s",list->dol_misc.dol_assign.dol_AssignName);
  275.             *ptr++=0;
  276.             break;
  277.         default:
  278.             *ptr++=0;
  279.         }
  280.         arr[n]=salloc(ptr+1-buf);
  281.         memcpy(arr[n++],buf,ptr+1-buf);
  282.     }
  283.     arr[n]=NULL;
  284.     Permit();
  285.  
  286.     QuickSort( arr, n );
  287.  
  288.     return arr;
  289. }
  290.  
  291.  
  292. do_join( void )
  293. {
  294.     BPTR sou, dest;
  295.     char *buffer;
  296.     int i;
  297.     long n;
  298.     char *namedest=av[--ac];
  299.  
  300.     if (options==0 && exists(namedest)) { ierror(namedest,203); return 20; }
  301.     if ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; }
  302.     if ( (dest=Open(namedest, MODE_NEWFILE)) == NULL )
  303.         { pError(namedest); goto fail1; }
  304.     for (i=1; i<ac; i++) {
  305.         if ( (sou=Open(av[i], MODE_OLDFILE)) == NULL ) pError(av[i]);
  306.         else
  307.             while( (n=Read(sou, buffer, 8192L)) > 0 )
  308.                 if (Write(dest, buffer, n) != n)
  309.                     { pError(namedest); Close(sou); goto fail2; }
  310.         Close(sou);
  311.     }
  312. fail2:
  313.     Close(dest);
  314. fail1:
  315.     free(buffer);
  316.     return 0;
  317. }
  318.  
  319. #define BUFDIM 512L
  320. #define MAXSTR 256
  321.  
  322. int minstr;
  323.  
  324. static int
  325. strings_in_file(long mask, char *s, char *path)
  326. {
  327.     char c;
  328.     char readbuf[BUFDIM+1], strbuf[MAXSTR+1];
  329.     int i, strctr=0;
  330.     BPTR fh;
  331.     int out, n, inter=IsInteractive(Output());;
  332.  
  333.     prepscroll(0);
  334.     if ( fh=Open(s, MODE_OLDFILE) ) {
  335.         fprintf(stdout, "Strings in %s (len>=%d):\n",path,minstr);
  336.         while ( (n=(int)Read(fh, readbuf, BUFDIM)) > 0 && !CHECKBREAK() )
  337.             for (i=0; i<n; i++) {
  338.                 c=readbuf[i];
  339.                 if (c<0x20 || c>0x7f) {
  340.                     out=(strctr>=minstr);
  341.                     if (!out) strctr=0;
  342.                 } else {
  343.                     strbuf[strctr++]=c;
  344.                     out=(strctr>=BUFDIM);
  345.                 }
  346.                 if (out) {
  347.                     strbuf[strctr]='\0';
  348.                     puts(strbuf);
  349.                     if( inter ) fflush(stdout);
  350.                     quickscroll();
  351.                     strctr=0;
  352.                 }
  353.             }
  354.         Close(fh);
  355.     } else
  356.         pError(s);
  357.     return 0;
  358. }
  359.  
  360. do_strings( void )
  361. {
  362.     minstr=myatoi(av[--ac],1,255);
  363.     all_args( strings_in_file, 0);
  364.     return 0;
  365. }
  366.  
  367. BPTR myfile[MAXMYFILES];
  368.  
  369. do_open( void )
  370. {
  371.     long mode;
  372.     int n;
  373.  
  374.     switch (toupper(av[2][0])) {
  375.         case 'R': mode=MODE_OLDFILE; break;
  376.         case 'W': mode=MODE_NEWFILE; break;
  377.         default : ierror(NULL,500); return 1;
  378.     }
  379.     n=myatoi(av[3],0,MAXMYFILES-1); if (atoierr) return 20;
  380.     if (myfile[n]) myclose(n);
  381.     myfile[n]=Open(av[1],mode);
  382.     return myfile[n]==NULL;
  383. }
  384.  
  385. do_close( void )
  386. {
  387.     int i, n;
  388.  
  389.     if (ac==1)
  390.         for (i=1; i<MAXMYFILES; i++)
  391.             myclose(i);
  392.     for (i=1; i<ac; i++) {
  393.         n=myatoi(av[i],0,MAXMYFILES-1); if (atoierr) return 20;
  394.         myclose(n);
  395.     }
  396.     return 0;
  397. }
  398.  
  399. void
  400. myclose(int n)
  401. {
  402.     if (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; }
  403. }
  404.  
  405. do_fileslist( void )
  406. {
  407.     int i, flag=0;
  408.  
  409.     printf("Open files:");
  410.     for (i=0; i<MAXMYFILES; i++)
  411.         if (myfile[i]) { printf(" %d",i); flag=1; }
  412.     if (!flag) printf(" None!");
  413.     printf("\n");
  414.     return 0;
  415. }
  416.  
  417. BPTR
  418. extOpen( char *name, long mode )
  419. {
  420.     if (name[0]=='.' && name[1]>='0' && name[1]<='9')
  421.         return myfile[atoi(name+1)];
  422.     return Open(name,mode);
  423. }
  424.  
  425.  
  426. void
  427. extClose(BPTR fh)
  428. {
  429.     int i;
  430.  
  431.     for (i=0; i<MAXMYFILES; i++)
  432.         if (myfile[i]==fh) return;
  433.     Close(fh);
  434. }
  435.  
  436. do_basename( void )
  437. {
  438.     char *res;
  439.     int  i;
  440.  
  441.     for( i=2; i<ac; i++ )
  442.         av[i]=BaseName(av[i]);
  443.     set_var(LEVEL_SET, av[1], res=compile_av(av,2,ac,0xA0,0));
  444.     free(res);
  445.     return 0;
  446. }
  447.  
  448. do_tackon( void )
  449. {
  450.     char buf[256];
  451.  
  452.     strcpy(buf, av[2]);
  453.     TackOn(buf, av[3]);
  454.     set_var(LEVEL_SET, av[1], buf);
  455.     return 0;
  456. }
  457.  
  458. extern char shellres[];
  459.  
  460. do_resident( void )
  461. {
  462.     int i=1;
  463.     struct ResidentProgramNode *p;
  464.     char buf[256];
  465.  
  466.     if (options==0 && ac>1) options=1;
  467.     switch (options) {
  468.     case 0:
  469.         ObtainSemaphore (& (ArpBase->ResPrgProtection) );
  470.         if (p=ArpBase->ResidentPrgList) {
  471.             printf("Name             Users Access\n");
  472.             for (; p; p=p->rpn_Next)
  473.                 printf("%-17s%5d%6d\n",
  474.                     p->rpn_Name, p->rpn_Usage, p->rpn_AccessCnt);
  475.         } else
  476.             printf("No resident program(s)\n");
  477.         ReleaseSemaphore(& (ArpBase->ResPrgProtection) );
  478.         break;
  479.     case 1:
  480.         for (; i<ac; i++)
  481.             if (loadres(av[i]))
  482.                 printf("OK! %s is now resident\n", BaseName(av[i]));
  483.             else
  484.                 pError(av[i]);
  485.         break;
  486.     case 2:
  487.         for (; i<ac; i++)
  488.             if (RemResidentPrg(av[i])) ierror(av[i],202);
  489.             else printf("Removed %s\n",av[i]);
  490.         break;
  491.     case 4:
  492.         for (; i<ac; i++) {
  493.             if( !o_resident ) {
  494.                 Setenv(shellres,"1");
  495.                 o_resident=1;
  496.             }
  497.             sprintf(buf,"res_%s",BaseName(av[i]));
  498.             Setenv(buf,av[i]);
  499.         }
  500.         break;
  501.     default:
  502.         ierror(NULL,500);
  503.         break;
  504.     }
  505.     return 0;
  506. }
  507.  
  508. int
  509. loadres(char *s)
  510. {
  511.     BPTR seg;
  512.  
  513.     if (seg=(BPTR)LoadPrg(s)) AddResidentPrg(seg,BaseName(s));
  514.     return (seg != NULL);
  515. }
  516.  
  517. static struct ProcessControlBlock pcb={
  518.     4000,        /* pcb_StackSize    */
  519.     0,            /* pcb_Pri            */
  520.     };
  521. /* remaining fields are NULL */
  522.  
  523. extern BPTR redir_out, redir_in;
  524.  
  525. struct TagItem tags[]={
  526.     {SYS_Input,  0},
  527.     {SYS_Output, 0},
  528.     {SYS_Asynch, 1},
  529.     {TAG_DONE,   0} };
  530.  
  531. do_truerun(char *avline, int backflag)
  532. {
  533.     BPTR input, output;
  534.     char name[100], *args, buf[10], *console=o_kick20 ? "CONSOLE:" : "*";
  535.     int cli, err;
  536.  
  537.     if (backflag) {
  538.         input = Open("NIL:",MODE_NEWFILE);
  539.         output= Open("NIL:",MODE_NEWFILE);
  540.     } else {
  541.         input = redir_in ?redir_in : Open("NIL:" , MODE_NEWFILE);
  542.         output= redir_out?redir_out: Open(console, MODE_NEWFILE);
  543.     }
  544.  
  545.     if( o_kick20 ) {
  546.         args=compile_av(av,1,ac,' ',1);
  547.  
  548.         tags[0].ti_Data= input;
  549.         tags[1].ti_Data= output;
  550.  
  551.         err=System( args, tags );
  552.  
  553.         if( err!=0 ) {
  554.             Close( tags[0].ti_Data );
  555.             Close( tags[1].ti_Data );
  556.             pError(av[1]);
  557.         }
  558.         free(args);
  559.     } else {
  560.         args=next_word(next_word(avline));
  561.  
  562.         pcb.pcb_Control= NULL;
  563.         pcb.pcb_Input  = input;
  564.         pcb.pcb_Output = output;
  565.  
  566.         if((cli=ASyncRun(av[1],args,&pcb))<0)
  567.             if (dofind(av[1], "", name,v_path))
  568.                 cli=ASyncRun(name,args,&pcb);
  569.  
  570.         sprintf(buf,"%d",cli);
  571.         set_var(LEVEL_SET,"_newproc",buf);
  572.     }
  573.  
  574.     if( cli<0 ) {
  575.         pError(av[1]);
  576.         return 20;
  577.     }
  578.  
  579.     return 0;
  580. }
  581.  
  582. #if 0
  583. extern BPTR redir_out, redir_in;
  584.  
  585. do_truerun(char *avline, int backflag)
  586. {
  587.     char name[100], *args, buf[10];
  588.     int cli;
  589.  
  590.     args=next_word(next_word(avline));
  591.     if (backflag) {
  592.         pcb.pcb_Control= 0;
  593.         pcb.pcb_Input  = Open("NIL:",MODE_OLDFILE);
  594.         pcb.pcb_Output = Open("NIL:",MODE_OLDFILE);
  595.     } else {
  596.         pcb.pcb_Control= 0;
  597.         pcb.pcb_Input  = redir_in;
  598.         pcb.pcb_Output = redir_out;
  599.  
  600.     }
  601.  
  602.     if((cli=ASyncRun(av[1],args,&pcb))<0)
  603.         if (dofind(av[1], "", name,v_path))
  604.             cli=ASyncRun(name,args,&pcb);
  605.  
  606.     if( cli<0 && cli>=-11 ) {
  607.         if( redir_out ) extClose( redir_out );
  608.         if( redir_in  ) extClose( redir_in  );
  609.     }
  610.  
  611.     sprintf(buf,"%d",cli);
  612.     set_var(LEVEL_SET,"_newproc",buf);
  613.  
  614.     if( cli<0 ) {
  615.         ierror(av[1],205);
  616.         return 20;
  617.     }
  618.     return 0;
  619. }
  620. #endif
  621.  
  622. int
  623. exists( char *name )
  624. {
  625.     BPTR lock;
  626.     char *nam=BaseName(name);
  627.     int ret=0;
  628.  
  629.     Myprocess->pr_WindowPtr = (APTR)(-1);
  630.     if ( strlen(nam)<=MAXFILENAME && (lock=Lock(name,ACCESS_READ))) {
  631.         UnLock(lock);
  632.         ret=1;
  633.     }
  634.     Myprocess->pr_WindowPtr = (APTR) o_noreq;
  635.     return ret;
  636. }
  637.  
  638. int
  639. mounted( char *dev )
  640. {
  641.     char *str, **get=expand_devs();
  642.  
  643.     while( (str=*get++) && Strcmp(str+1,dev) ) ;
  644.     free_expand(get);
  645.     return (int)str;
  646. }
  647.  
  648. do_aset( void )
  649. {
  650.     Setenv(av[1],av[2]);
  651.     return 0;
  652. }
  653.  
  654. #define HTYPELINE 16L
  655.  
  656. static int
  657. htype_a_file(long mask, char *s, char *path)
  658. {
  659.     BPTR fh;
  660.     long n, filesize=0;
  661.     UBYTE buf[HTYPELINE+1];
  662.     char out[80], *put;
  663.     int i, inter=IsInteractive(Output());
  664.  
  665.     if ( (fh=Open(s,MODE_OLDFILE))==NULL ) { pError(s); return 20; }
  666.     prepscroll(0);
  667.     while ( (n=Read(fh,(char *)buf,HTYPELINE))>0 && !dobreak()) {
  668.         put=out;
  669.         put+=sprintf(put,"%06lx: ",filesize);
  670.         filesize+=n;
  671.         for (i=0; i<n; i++) {
  672.             put+=sprintf( put,(i&3) ? "%02x" : " %02x",buf[i]);
  673.             if ((buf[i]&127)<0x20) buf[i]='.';
  674.         }
  675.         for ( ; i<HTYPELINE; i++) {
  676.             put+=sprintf( put, (i&3) ? "  " : "   ");
  677.             buf[i]=' ';
  678.         }
  679.         buf[i]=0;
  680.         sprintf(put,"    %s",buf);
  681.         puts(out);
  682.         if( inter ) fflush(stdout);
  683.         quickscroll();
  684.     }
  685.     Close(fh);
  686.     return 0;
  687. }
  688.  
  689. do_htype( void )
  690. {
  691.     all_args( htype_a_file, 0);
  692.     return 0;
  693. }
  694.  
  695. do_stack( void )
  696. {
  697.     long n;
  698.  
  699.     if (ac>1) {
  700.         n=Atol(av[1]);
  701.         if (!IoErr()) Mycli->cli_DefaultStack=(long)(n >> 2L);
  702.     }
  703.     else printf("current stack size is %ld bytes\n",
  704.                 (long)Mycli->cli_DefaultStack << 2L);
  705.     return 0;
  706. }
  707.  
  708. do_fault( void )
  709. {
  710.     PERROR *p;
  711.     int i, n;
  712.  
  713.     for (i=1; i<ac; i++) {
  714.         n=myatoi(av[i],0,32767);
  715.         if (!atoierr) {
  716.             for (p=Perror; p->errnum && p->errnum!=n; p++);
  717.             if (p->errnum)
  718.                 printf("Fault %d: %s\n",n,p->errstr);
  719.             else
  720.                 printf("Fault %d not recognized\n",n);
  721.         }
  722.     }
  723.     return 0;
  724. }
  725.  
  726. struct rpncommand {
  727.     char *str;
  728.     int parsin, parsout;
  729.     };
  730.  
  731. static struct rpncommand rpn[]={
  732.     "+",    2,    1,
  733.     "-",    2,    1,
  734.     "*",    2,    1,
  735.     "/",    2,    1,
  736.     "%",    2,    1,
  737.     "&",    2,    1,
  738.     "|",    2,    1,
  739.     "~",    1,    1,
  740.     ">",    2,    1,
  741.     "<",    2,    1,
  742.     "==",    2,    1,
  743.     "!",    1,    1,
  744.     "MAX",    2,    1,
  745.     "MIN",    2,    1,
  746.     "DUP",    1,    2,
  747.     "DROP",    1,    0,
  748.     "SWAP",    2,    2,
  749.     "HELP",    0,    0,
  750.     NULL,    0,    1,    /* this looks for a number */
  751. };
  752.  
  753. static long stack[50];
  754. static int sp;
  755.  
  756.  
  757. eval_rpn( char **av, int ac, int flag )
  758. {
  759.     char *zero="Division by zero\n";
  760.     struct rpncommand *temp;
  761.     long n0, n1, t;
  762.     int j, i=0, oldsp=sp;
  763.  
  764.     for (; i<ac; i++) {
  765.         for (j=0; rpn[j].str && Strcmp(rpn[j].str,av[i]); j++) ;
  766.         n0=stack[sp-1];
  767.         n1=stack[sp-2];
  768.         sp -= (rpn[j].parsin);
  769.         if (sp<0) { fprintf(stderr, "RPN: Empty stack\n"); goto error; }
  770.         switch (j) {
  771.           case 0:    n0 += n1;            break;
  772.           case 1:    n0 = n1-n0;            break;
  773.           case 2:    n0 *= n1;            break;
  774.           case 3:    if(n0) n0=n1/n0; else fprintf(stderr,zero); break;
  775.           case 4:    if(n0) n0=n1%n0; else fprintf(stderr,zero); break;
  776.           case 5:    n0 &= n1;            break;
  777.           case 6:    n0 |= n1;            break;
  778.           case 7:    n0 =  ~n0    ;        break;
  779.           case 8:    n0 = (n1 > n0);        break;
  780.           case 9:    n0 = (n1 < n0);        break;
  781.           case 10:    n0 = (n0 == n1);    break;
  782.           case 11:    n0 = !n0;            break;
  783.           case 12:    n0=n1>n0 ? n1 : n0;    break;
  784.           case 13:    n0=n1<n0 ? n1 : n0;    break;
  785.           case 14:    n1=n0;                break;
  786.           case 15:    t=n0; n0=n1; n1=t;    break;
  787.           case 16:                        break;
  788.           case 17:    printf("In Commands Out\n");
  789.             for (temp=rpn; temp->str; temp++)
  790.                 printf(" %d %-10s%d\n",
  791.                 temp->parsin,temp->str,temp->parsout);
  792.             break;
  793.           default:    n0=Atol(av[i]);
  794.                 if (IoErr()) {
  795.                     fprintf(stderr, "Bad RPN cmd: %s\n",av[i]);
  796.                     goto error;
  797.                 }
  798.                 break;
  799.           }
  800.         stack[sp]=n0;
  801.         stack[sp+1]=n1;
  802.         sp += rpn[j].parsout;
  803.     }
  804.     if( flag && sp-1)
  805.         fprintf( 
  806.           stderr,
  807.           "RPN: Stack not empty\n"
  808.         );
  809.  
  810.     t=sp; sp=oldsp;
  811.     if( flag )
  812.         return stack[t-1]; /* return top value */
  813.     else 
  814.         return t-sp;
  815.  
  816. error:
  817.     sp=oldsp;
  818.     return 0;
  819. }
  820.  
  821.  
  822. do_rpn(char *garbage,int ifflag) /* ifflag!=0 if called from if */
  823. {
  824.     int i=1;
  825.     long t;
  826.  
  827.     t=eval_rpn( av+i, ac-i, ifflag );
  828.     if (ifflag) return t;              /* called from if: return top value */
  829.     for (i=sp+t-1;i>=sp;i--) printf("%ld\n", stack[i]);/* else print stack */
  830.  
  831.     return t ? 0 : 20;
  832. }
  833.  
  834. do_path( void )
  835. {
  836.     ULONG ll, ll1, *lp, new, *newp;
  837.     char buf[256];
  838.     BPTR lock;
  839.     int i;
  840.  
  841.     if( options&1 ) {
  842.         Forbid();
  843.         for( ll= Mycli->cli_CommandDir; ll; ll= ll1 ) {
  844.             lp=(ULONG *)(4*ll);
  845.             ll1=lp[0];
  846.             UnLock(lp[1]);
  847.             DosFreeMem( lp );
  848.         }
  849.         Mycli->cli_CommandDir=0;
  850.         Permit();
  851.     } else if( ac==1 ) {     /* Should Forbid() here, but puts() Permit()s */
  852.         puts("Current dir"); /* and failure here is not really harmful...  */
  853.         for( ll= Mycli->cli_CommandDir; ll; ll= *lp ) {
  854.             lp=(ULONG *)(4*ll);
  855.             PathName(lp[1], buf, 256L);
  856.             puts(buf);
  857.         }
  858.         puts("C:");
  859.         return 0;
  860.     }
  861.     for( i=1; i<ac; i++ ) {
  862.         if( !(lock=Lock(av[i],ACCESS_READ)) ) {
  863.             ierror(av[i],205);
  864.             continue;
  865.         }
  866.         if( !isdir(av[i])) {
  867.             ierror(av[i],212);
  868.             UnLock(lock);
  869.             continue;
  870.         }
  871.         Forbid();
  872.         for( ll= Mycli->cli_CommandDir, lp=NULL; ll; ll= lp[0] ) {
  873.             lp=(ULONG *)(4*ll);
  874.             if( CompareLock(lp[1],lock)==LCK_EQUAL) {
  875.                 UnLock(lock), lock=0;
  876.                 break;
  877.             }
  878.         }
  879.         if( lock && (newp=DosAllocMem( 8 ))) {
  880.             newp[1]=lock;
  881.             new =(ULONG)newp/4;
  882.             if( lp )
  883.                 *lp=new;
  884.             else
  885.                 Mycli->cli_CommandDir=new;
  886.         }
  887.         Permit();
  888.     }
  889.     return 0;
  890. }
  891.  
  892. do_pri( void )
  893. {
  894.     int t, pri;
  895.     struct Process *proc;
  896.  
  897.     t=(int)(long)FindCLI(0L);
  898.     t=myatoi(av[1],0,t); if (atoierr) return 20;
  899.     pri=myatoi(av[2],-128,127); if (atoierr) return 20;
  900.     Forbid();
  901.     proc=(t==0 ? Myprocess : FindCLI((long)t));
  902.     if (proc==NULL) fprintf(stderr, "process not found\n");
  903.     else SetTaskPri((struct Task *)proc, (long)pri);
  904.     Permit();
  905.     return 0;
  906. }
  907.  
  908. do_strleft( void )
  909. {
  910.     int n;
  911.  
  912.     n=posatoi(av[3]); if (atoierr) return 20;
  913.     set_var_n(LEVEL_SET, av[1], av[2], n);
  914.     return 0;
  915. }
  916.  
  917. do_strright( void )
  918. {
  919.     int n, len=strlen(av[2]);
  920.  
  921.     n=posatoi(av[3]); if (atoierr) return 20;
  922.     if( n>len ) n=len;
  923.     set_var(LEVEL_SET, av[1], av[2]+len-n );
  924.     return 0;
  925. }
  926.  
  927. do_strmid( void )
  928. {
  929.     int n1, n2=999999, len=strlen(av[2]);
  930.  
  931.     n1=myatoi(av[3],1,999999)-1; if (atoierr) return 20;
  932.     if (n1>len) n1=len;
  933.     if (ac>4) {
  934.         n2=posatoi(av[4]); if (atoierr) return 20;
  935.     }
  936.     set_var_n(LEVEL_SET, av[1], av[2]+n1, n2);
  937.     return 0;
  938. }
  939.  
  940. do_strlen( void )
  941. {
  942.     char buf[16];
  943.  
  944.     sprintf(buf,"%d",strlen(av[2]));
  945.     set_var(LEVEL_SET, av[1], buf);
  946.     return 0;
  947. }
  948.  
  949. int atoierr;
  950.  
  951. myatoi(char *s,int mmin,int mmax)
  952. {
  953.     int n;
  954.  
  955.     n=Atol(s);
  956.     if (atoierr=IoErr())
  957.         ierror(s,511);
  958.     else if (n<mmin || n>mmax) {
  959.         atoierr=1; n=mmin;
  960.         fprintf( stderr, "%s(%d) not in (%d,%d)\n",s,n,mmin,mmax );
  961.     }
  962.     return n;
  963. }
  964.  
  965. unlatoi(char *s)
  966. {
  967.     int n=Atol(s);
  968.     if (atoierr=IoErr())
  969.         ierror(s,511), n=0;
  970.     return n;
  971. }
  972.  
  973. posatoi(char *s)
  974. {
  975.     int n=Atol(s);
  976.     if (atoierr=IoErr())
  977.         ierror(s,511);
  978.     else if (n<0 )
  979.         atoierr=1, n=0, fprintf( stderr, "%s must be positive\n",s );
  980.     return n;
  981. }
  982.  
  983.  
  984. do_fltlower( void )
  985. {
  986.     return line_filter( strlwr );
  987. }
  988.  
  989. do_fltupper( void )
  990. {
  991.     return line_filter( strupr );
  992. }
  993.  
  994. #if 0
  995. char *
  996. stripcr( char *get )
  997. {
  998.     char *old=get, *put;
  999.  
  1000.     for( put=get; *get; get++ )
  1001.         if( *get!=13 )
  1002.             *put++=*get;
  1003.     *put++=0;
  1004.     return old;
  1005. }
  1006.  
  1007. do_fltstripcr( void )
  1008. {
  1009.     return line_filter( stripcr );
  1010. }
  1011. #endif
  1012.  
  1013. static int
  1014. line_filter( char *(*func)( char * ) )
  1015. {
  1016.     char buf[256];
  1017.  
  1018.     while (!CHECKBREAK() && myfgets(buf,stdin))
  1019.         puts((*func)(buf));
  1020.     return 0;
  1021. }
  1022.  
  1023. int
  1024. do_linecnt( void )
  1025. {
  1026.     int count=0;
  1027.     char buf[256];
  1028.  
  1029.     while (!CHECKBREAK() && fgets(buf,255,stdin)) ++count;
  1030.     printf("%d lines\n",count);
  1031.     return 0;
  1032. }
  1033.  
  1034. int
  1035. do_uniq( void )
  1036. {
  1037.     int firstline=1;
  1038.     char buf[256], oldbuf[256];
  1039.  
  1040.     while (!CHECKBREAK() && myfgets(buf,stdin)) {
  1041.         if ( firstline || strcmp(buf, oldbuf)) {
  1042.             strcpy(oldbuf, buf);
  1043.             puts(buf);
  1044.         }
  1045.         firstline=0;
  1046.     }
  1047.     return 0;
  1048. }
  1049.  
  1050.  
  1051. #define RXFB_RESULT  17
  1052. #define RXCOMM    0x01000000
  1053.  
  1054. static struct rexxmsg {
  1055.     struct Message rm_Node;             /* EXEC message structure        */
  1056.     APTR     rm_TaskBlock;              /* global structure (private)    */
  1057.     APTR     rm_LibBase;                /* library base (private)        */
  1058.     LONG     rm_Action;                 /* command (action) code         */
  1059.     LONG     rm_Result1;                /* primary result (return code)  */
  1060.     LONG     rm_Result2;                /* secondary result              */
  1061.     STRPTR   rm_Args[16];               /* argument block (ARG0-ARG15)   */
  1062.  
  1063.     struct MsgPort *rm_PassPort;        /* forwarding port               */
  1064.     STRPTR   rm_CommAddr;               /* host address (port name)      */
  1065.     STRPTR   rm_FileExt;                /* file extension                */
  1066.     LONG     rm_Stdin;                  /* input stream (filehandle)     */
  1067.     LONG     rm_Stdout;                 /* output stream (filehandle)    */
  1068.     LONG     rm_avail;                  /* future expansion              */
  1069. } mymsg;                                /* size: 128 bytes               */
  1070.  
  1071.  
  1072. do_rxsend( char *avline )
  1073. {
  1074.     int i, ret=0;
  1075.     long result;
  1076.     struct MsgPort *port, *reply;
  1077.     long len;
  1078.     char buf[20], *resptr;
  1079.  
  1080.     if (!(port = (struct MsgPort *)FindPort(av[1])))
  1081.         { fprintf(stderr, "No port %s!\n", av[1]); return 20; }
  1082.     mymsg.rm_Node.mn_Node.ln_Type = NT_MESSAGE;
  1083.     mymsg.rm_Node.mn_Length = sizeof(struct rexxmsg);
  1084.     mymsg.rm_Action = RXCOMM | (options&1 ? 1L << RXFB_RESULT : 0);
  1085.     if (!(reply = CreatePort(NULL, 0L))) {
  1086.         fprintf(stderr, "No reply port\n");
  1087.         return 20;
  1088.     }
  1089.     mymsg.rm_Node.mn_ReplyPort = reply;
  1090.  
  1091.     if( options&2 )
  1092.         av[2]=compile_av( av,2,ac,' ',0), ac=3;
  1093.     for ( i=2; i<ac; i++) {
  1094.         mymsg.rm_Args[0] = av[i];
  1095.         mymsg.rm_Result2 = 0;        /* clear out the last result. */
  1096.         PutMsg(port, &mymsg.rm_Node);
  1097.  
  1098.         Wait( 1<<reply->mp_SigBit | SIGBREAKF_CTRL_C );
  1099.  
  1100.         if( CHECKBREAK() ) {
  1101.             ret=5;
  1102.             break;
  1103.         }
  1104.  
  1105.         if (options&1) {
  1106.             if( (result=mymsg.rm_Result2)<1000000 ) { /* like AREXX */
  1107.                 sprintf(buf,"%d",result);              
  1108.                 set_var(LEVEL_SET,v_result,buf);
  1109.             } else {
  1110.                 resptr=(char *)(result-4);
  1111.                 len=*(long *)resptr;
  1112.                 memmove(resptr,resptr+4,len);  /* Null terminate */
  1113.                 resptr[len]=0;      
  1114.                 set_var(LEVEL_SET,v_result,resptr);
  1115.                 FreeMem(resptr, len+4 );
  1116.             }
  1117.         } else 
  1118.             unset_var( LEVEL_SET, v_result );
  1119.     }
  1120.     if( options&2 )
  1121.         free( av[2] );
  1122.  
  1123.     if (reply) DeletePort(reply);
  1124.     return ret;
  1125. }
  1126.  
  1127. static char *rxreturn;
  1128.  
  1129. do_rxrec( void )
  1130. {
  1131.     struct MsgPort *port;
  1132.     struct rexxmsg *msg;
  1133.     char *portname, *str;
  1134.  
  1135.     if (ac > 1)
  1136.         portname=av[1];
  1137.     else
  1138.         portname="rexx_csh";
  1139.  
  1140.     port=CreatePort(portname, 0L);
  1141.     if (port==NULL) {
  1142.         fprintf(stderr, "Can't have MsgPort %s\n", portname);
  1143.         return 20;
  1144.     }
  1145.     for (;;) {
  1146.         WaitPort(port);
  1147.         while (msg=(struct rexxmsg *)GetMsg(port)) {
  1148.             if ( ! Strcmp(msg->rm_Args[0], "bye")) {
  1149.                 ReplyMsg((struct Message *)msg);
  1150.                 DeletePort(port);
  1151.                 return 0;
  1152.             }
  1153.             rxreturn=NULL;
  1154.             exec_command(msg->rm_Args[0]);
  1155.             if (msg->rm_Action & (1L << RXFB_RESULT)) {
  1156.                 if( rxreturn ) {
  1157.                     str= SAllocMem( strlen( rxreturn )+5 , 0 );
  1158.                     *(long *)str=strlen( rxreturn );
  1159.                     strcpy( str+4, rxreturn );
  1160.                     msg->rm_Result2=(long)str;
  1161.                 } else {
  1162.                     str = get_var(LEVEL_SET, v_lasterr);
  1163.                     msg->rm_Result2=(str) ? atoi(str) : 20;
  1164.                 }
  1165.             }
  1166.             ReplyMsg((struct Message *)msg);
  1167.         }
  1168.     }
  1169. }
  1170.  
  1171. int
  1172. do_waitport( void )
  1173. {
  1174.     int count=4*10;
  1175.     struct MsgPort *port=NULL;
  1176.  
  1177.     if( ac==3 ) 
  1178.         { count=2*myatoi(av[2],0, 32000); if( atoierr ) return 20; }
  1179.  
  1180.     while( --count>=0 && !(port=FindPort(av[1])) && !dobreak() )
  1181.         Delay(12);
  1182.  
  1183.     return port ? 0 : 20;
  1184. }
  1185.  
  1186. int
  1187. do_rxreturn( void )
  1188. {
  1189.     rxreturn=compile_av( av, 1, ac, ' ', 1 );
  1190.     return 0;
  1191. }
  1192.  
  1193. do_ascii( void )
  1194. {
  1195.     int x=1, y, c, c1, t;
  1196.     char *fmt1=" %3d %c%c |", *fmt2=" %4d";
  1197.  
  1198.     if( options&1 ) fmt1=" %3o %c%c |", fmt2="%4o";
  1199.     if( options&2 ) fmt1=" %3x %c%c |", fmt2="%4x";
  1200.     if( ac==x )
  1201.         for( y=0; y<32 && !dobreak(); y++ ) {
  1202.             printf("|");
  1203.             for( x=0; x<8; x++ ) {
  1204.                 c1=c=y+32*x; t=' ';
  1205.                 if( c<32 ) t='^', c1+=64;
  1206.                 printf(fmt1,c, t, c1<128 || c1>=160?c1:'.');
  1207.             }
  1208.             printf("\n");
  1209.         }
  1210.     else 
  1211.         for( ; x<ac && !dobreak(); x++ ) {
  1212.             for( y=0; y<strlen(av[x]); y++ )
  1213.                 printf(fmt2,av[x][y]);
  1214.             printf("\n");
  1215.         }
  1216.     return 0;
  1217. }
  1218.  
  1219. void
  1220. appendslash( char *path )
  1221. {
  1222.     int c;
  1223.  
  1224.     if( (c=path[strlen(path)-1]) !='/' && c!=':' )
  1225.         strcat(path,"/");
  1226. }
  1227.  
  1228. static void
  1229. whereis( char *path, char *file )
  1230. {
  1231.     char **eav, buf[100];
  1232.     int  eac, j;
  1233.  
  1234.     buf[0]=0;
  1235.     if( path ) {
  1236.         strcpy(buf,path);
  1237.         appendslash(buf);
  1238.     }
  1239.     strcat(buf,".../");
  1240.     strcat(buf,file);
  1241.     if( !index( file, '*' ) && !index( file, '?') )
  1242.         strcat(buf,"*");
  1243.     if(eav=expand(buf,&eac)) {
  1244.         for( j=0; j<eac && !dobreak(); j++ )
  1245.             printf("%s\n",eav[j]);
  1246.         free_expand(eav);
  1247.     }
  1248. }
  1249.  
  1250. do_whereis( void )
  1251. {
  1252.     char buf[200], *prev, *devs;
  1253.     int i;
  1254.  
  1255.     if( index( av[1],':') || index( av[1],'/' ) )
  1256.         { fprintf(stderr,"No paths please\n"); return 20; };
  1257.  
  1258.     if( options&1 ) {
  1259.         Myprocess->pr_WindowPtr = (APTR)(-1);
  1260.         get_drives( devs=buf );
  1261.         do {
  1262.             prev=devs; devs=index(devs,0xA0);
  1263.             if( devs ) *devs++=0; 
  1264.             whereis( prev, av[1] );
  1265.         } while( devs );
  1266.         Myprocess->pr_WindowPtr = (APTR) o_noreq;
  1267.     } else if( ac==2 ) {
  1268.         whereis( NULL, av[1] );
  1269.     } else {
  1270.         for( i=2; i<ac; i++ ) {
  1271.             strcpy(buf,av[i]);
  1272.             appendslash( buf );
  1273.             whereis( buf, av[1] );
  1274.         }
  1275.     }
  1276.     return 0;
  1277. }
  1278.  
  1279. do_usage( void )
  1280. {
  1281.     int i;
  1282.  
  1283.     if( ac==1 ) {
  1284.         printf("Usage: usage [command...command]\n");
  1285.         printf("[ ]=option   [ | ]=choice   { }=repetition   name...name=1 or more names\n");
  1286.     } else 
  1287.         for( i=1; i<ac; i++ )
  1288.             show_usage( av[i] );
  1289.     return 0;
  1290. }
  1291.  
  1292. int NumMenus;
  1293.  
  1294. do_menu( void )
  1295. {
  1296.     if( o_nowindow )
  1297.         return 5;
  1298.  
  1299.     if( options&1 )
  1300.         remove_menu();
  1301.  
  1302.     if( ac==2 )
  1303.         show_usage( NULL );
  1304.     else if( NumMenus<MAXMENUS && ac!=1)
  1305.         install_menu( av+1, ac-1 );
  1306.  
  1307.     set_menu();
  1308.     return 0;
  1309. }
  1310.  
  1311. #define NUMITE 40
  1312. #define TITWID 90
  1313. #define ITEWID 148
  1314.  
  1315. static struct Menu DefaultMenu= {0, 0,0,TITWID,10, MENUENABLED,0,0};
  1316. static struct IntuiText DefaultIntuiText= {0,1,JAM2, 1,1,NULL,0,0};
  1317. static struct MenuItem DefaultMenuItem=
  1318.   {0, 0,0,ITEWID,0, HIGHCOMP|ITEMTEXT|ITEMENABLED,0,0,0,0,0,0};
  1319.  
  1320. struct Menu Menus[10];
  1321. char *MenuCommand[MAXMENUS][MAXITEMS];
  1322.  
  1323. static void
  1324. install_menu( char *mav[], int mac )
  1325. {
  1326.     struct TextAttr *ta;
  1327.     struct Menu *m;
  1328.     struct MenuItem *mi, **pmi;
  1329.     struct IntuiText *it;
  1330.     int y, i, fonthei;
  1331.     char *p, *com;
  1332.  
  1333.     if( o_nowindow || !Win )
  1334.         return;
  1335.  
  1336.     if( mac>=MAXITEMS )
  1337.         mac=MAXITEMS-1;
  1338.  
  1339.     ClearMenuStrip( Win );
  1340.     Delay(3);
  1341.  
  1342.     if( NumMenus )
  1343.         Menus[NumMenus-1].NextMenu=Menus+NumMenus;
  1344.     m  =&Menus[NumMenus];
  1345.     *m =DefaultMenu;
  1346.     m->LeftEdge  = NumMenus*TITWID;
  1347.     m->MenuName  = strcpy(salloc(strlen(mav[0])+1),mav[0]);
  1348.     if( strlen(m->MenuName)>TITWID/8 )
  1349.         m->MenuName[TITWID/8+1]=0;
  1350.     DefaultIntuiText.ITextFont=ta=Win->WScreen->Font;
  1351.     DefaultMenuItem.Height=2+(fonthei=ta->ta_YSize);
  1352.  
  1353.     y=0;
  1354.     pmi=&m->FirstItem;
  1355.     for( i=1; i<mac; i++) {
  1356.         it =(void *)salloc(sizeof(struct IntuiText));
  1357.         *it=DefaultIntuiText;
  1358.         mi =(void *)salloc(sizeof(struct MenuItem ));
  1359.         *mi=DefaultMenuItem;
  1360.  
  1361.         com=NULL;
  1362.         if( p=index(mav[i],',')) {
  1363.             *p=0; com=++p;
  1364.             if( p=index(com,',')) {
  1365.                 *p=0;
  1366.                 mi->Command=p[1];
  1367.                 mi->Flags |=COMMSEQ;
  1368.             }
  1369.         }
  1370.  
  1371.         if( !com || !*com) {
  1372.             com=strcpy(salloc(strlen(mav[i])+2),mav[i]);
  1373.             MenuCommand[NumMenus][i-1]=com;
  1374.             com+=strlen(com);
  1375.             *com++=13;
  1376.             *com=0;
  1377.         } else {
  1378.             MenuCommand[NumMenus][i-1]=strcpy(salloc(strlen(com)+1),com);
  1379.         }
  1380.  
  1381.         it->IText=(UBYTE *)strcpy(salloc(strlen(mav[i])+2),mav[i]);
  1382.  
  1383.         *pmi= mi;
  1384.         pmi = &mi->NextItem;
  1385.         mi->TopEdge = y;
  1386.         mi->ItemFill= (APTR)it;
  1387.  
  1388.         y+=DefaultMenuItem.Height;
  1389.     }
  1390.  
  1391.     NumMenus++;
  1392. MError:
  1393.     return;
  1394. }
  1395.  
  1396.  
  1397. void
  1398. remove_menu()
  1399. {
  1400.     if( NumMenus>0 ) {
  1401.         struct MenuItem *mi, *nextmi;
  1402.         int i,j;
  1403.  
  1404.         for( i=0; i<NumMenus; i++ ) {
  1405.             for( mi=Menus[i].FirstItem,j=0 ; mi; mi=nextmi,j++ ) {
  1406.                 free( ((struct IntuiText *)mi->ItemFill)->IText );
  1407.                 free( ((struct IntuiText *)mi->ItemFill) );
  1408.                 nextmi=mi->NextItem;
  1409.                 free(mi);
  1410.                 free(MenuCommand[i][j]);
  1411.             }
  1412.         }
  1413.  
  1414.         NumMenus=0;
  1415.         set_menu();
  1416.     }
  1417. }
  1418.  
  1419.  
  1420. void
  1421. set_menu()
  1422. {
  1423.     if( o_nowindow || !Win )
  1424.         return;
  1425.  
  1426.     if( NumMenus>0 )
  1427.         SetMenuStrip( Win, Menus );
  1428.     else 
  1429.         ClearMenuStrip( Win );
  1430.  
  1431.     Delay(3);
  1432. }
  1433.  
  1434. int
  1435. do_getenv( void )
  1436. {
  1437.     char buf[256], *val=buf;
  1438.  
  1439.     if( ac!=3 && ac!=2 ) {
  1440.         show_usage( NULL );
  1441.         return 20;
  1442.     }
  1443.     if( !Getenv(av[ac-1],buf,256))
  1444.         val="";
  1445.  
  1446.     if( ac==2 )
  1447.         printf( "%s\n", val );
  1448.     else 
  1449.         set_var( LEVEL_SET, av[1], val );
  1450.     return 0;
  1451. }
  1452.  
  1453. int
  1454. do_setenv( void )
  1455. {
  1456.     if( ac!=3 ) {
  1457.         show_usage( NULL );
  1458.         return 20;
  1459.     } else
  1460.         setenv( av[1], av[2] );
  1461.     return 0;
  1462. }
  1463.  
  1464. char **
  1465. read_name( char *name, int *ac )
  1466. {
  1467.     FILE *file;
  1468.     char **av=NULL;
  1469.  
  1470.     *ac=0;
  1471.     if( file=name ? fopen( name, "r") : stdin ) {
  1472.         av=read_file( file, ac );
  1473.         if( name ) fclose( file );
  1474.     } else 
  1475.         pError( name );
  1476.     return av;
  1477. }
  1478.  
  1479.  
  1480. char **
  1481. read_file( FILE *file, int *ac )
  1482. {
  1483.     int buflen=4096, lines=0, i, offs, got=0;
  1484.     char *buf, *tmp, *ptr, **lineptr;
  1485.  
  1486.     if( !(buf=ptr=DosAllocMem( buflen )))
  1487.         goto error;
  1488.     do {
  1489.         while( ptr+400 < buf+buflen && (got=myfgets(ptr, file)) && !dobreak())
  1490.             ptr+=strlen(ptr)+1, lines++;
  1491.         if( ptr+256 < buf+buflen ) {
  1492.             offs=ptr-buf;
  1493.             if( !(tmp=DosAllocMem( buflen*2 )))
  1494.                 goto error;
  1495.             memcpy( tmp, buf, buflen );
  1496.             DosFreeMem( buf );
  1497.             buflen*=2, buf=tmp;
  1498.             ptr=buf+offs;
  1499.         }
  1500.     } while( got && !dobreak());
  1501.     if( !(lineptr=(char **)DosAllocMem( (lines+1)*sizeof( char * ))))
  1502.         goto error;
  1503.     *lineptr++=buf;
  1504.     for( ptr=buf, i=0; i<lines; i++ ) {
  1505.         lineptr[i]=ptr;
  1506.         ptr+=strlen(ptr)+1;
  1507.     }
  1508.     *ac=lines;
  1509.     return lineptr;
  1510.  
  1511. error:
  1512.     if( buf ) DosFreeMem( buf );
  1513.     fprintf( stderr, "Out of memory\n" );
  1514.     *ac=0;
  1515.     return NULL;
  1516. }
  1517.  
  1518. void
  1519. free_file( ptr )
  1520.     char **ptr;
  1521. {
  1522.     if( ptr-- ) {
  1523.         if( *ptr )
  1524.             DosFreeMem( *ptr );
  1525.         DosFreeMem(ptr);
  1526.     }
  1527. }
  1528.  
  1529.  
  1530. do_qsort( void )
  1531. {
  1532.     char **lineptr;
  1533.     int  lines, i;
  1534.  
  1535.     if( ac==1 ) {
  1536.         lineptr=read_file( stdin, &lines);
  1537.         DirQuickSort( lineptr, lines, cmp, options&1, 0 );
  1538.         prepscroll(0);
  1539.         for( i=0; i<lines && !dobreak(); i++ ) {
  1540.             quickscroll();
  1541.             puts( lineptr[i] );
  1542.         }
  1543.         free_file( lineptr );
  1544.     } else
  1545.         ierror( NULL,506 );
  1546.     return 0;
  1547. }
  1548.  
  1549. extern int w_width;
  1550.  
  1551. do_truncate( void )
  1552. {
  1553.     char buf[256];
  1554.     int  w=newwidth(), c;
  1555.     char *ptr;
  1556.  
  1557.     if( ac==2 )
  1558.         w=atoi( av[1] );
  1559.  
  1560.     prepscroll(0);
  1561.     while( myfgets(buf,stdin) && !dobreak() ) {
  1562.         for( c=0, ptr=buf; *ptr && c<w; ptr++ )
  1563.             if( *ptr=='\t' )
  1564.                 c+=8-(c&7);
  1565.             else if( *ptr==27 ) {
  1566.                 while( *ptr<'@' )
  1567.                     ptr++;
  1568.             } else 
  1569.                 c++;
  1570.         *ptr=0;
  1571.         quickscroll();
  1572.         puts(buf);
  1573.     }
  1574.     return 0;
  1575. }
  1576.  
  1577. int
  1578. do_readfile( void )
  1579. {
  1580.     char **rav, *str=NULL, *file=NULL;
  1581.     int rac;
  1582.  
  1583.     if( ac>2 ) file=av[2];
  1584.     if( rav=read_name( file, &rac ) ) { 
  1585.         if( str= compile_av( rav, 0, rac, 0xA0, 0 ) )
  1586.             set_var( LEVEL_SET, av[1], str );
  1587.         free_file( rav );
  1588.     }
  1589.     return str ? 0 : 20;
  1590. }
  1591.  
  1592. void
  1593. foreach( char **s, int (*func)(char *s) )
  1594. {
  1595.     char *str;
  1596.  
  1597.     for( ;; ) {
  1598.         str=*s;
  1599.         if( !(*s=index(*s,0xA0)))
  1600.             break;
  1601.         **s=0;
  1602.         (*func)(str);
  1603.         *(*s)++=0xA0;
  1604.         if( breakcheck())
  1605.             return;
  1606.     }
  1607.     (*func)(str);
  1608. }
  1609.  
  1610. int
  1611. do_writefile( void )
  1612. {
  1613.     char *ptr;
  1614.  
  1615.     if( !(ptr=get_var(LEVEL_SET,av[1])))
  1616.         { fprintf(stderr,"Undefined variable %s\n",av[1]); return 20; }
  1617.  
  1618.     foreach( &ptr, puts );
  1619.  
  1620.     return 0;
  1621. }
  1622.  
  1623. int
  1624. do_split( void )
  1625. {
  1626.     int i;
  1627.     char *val, *gap, *oldval;
  1628.  
  1629.     if( !(val=get_var( LEVEL_SET, av[1] )))
  1630.         { fprintf( stderr, "undefined variable %s\n", av[1] ); return 20; }
  1631.     oldval=val=strcpy(salloc(strlen(val)+1),val);
  1632.     for( i=2; i<ac-1; i++ ) {
  1633.         if( gap=index(val,0xA0 )) *gap=0;
  1634.         set_var( LEVEL_SET, av[i], val );
  1635.         val="";
  1636.         if( gap ) *gap=0xA0, val=gap+1;
  1637.     }
  1638.     set_var( LEVEL_SET, av[ac-1], val );
  1639.     free(oldval);
  1640.     return 0;
  1641. }
  1642.  
  1643. char *
  1644. copyof( char *str )
  1645. {
  1646.     return strcpy(salloc(strlen(str)+1),str);
  1647. }
  1648.  
  1649. int
  1650. do_class( char *avline )
  1651. {
  1652.     CLASS *new;
  1653.  
  1654.     if( options&1 ) {
  1655.         avline=next_word(avline);
  1656.         for( new=CRoot,CRoot=NULL; new; new=new->next )
  1657.             Free(new);
  1658.     }
  1659.  
  1660.     if( ac==1 ) {
  1661.         for( new=CRoot; new; new=new->next )
  1662.             printf("%s\n",new->name);
  1663.         return 0;
  1664.     }
  1665.  
  1666.     avline=next_word(avline);
  1667.     if(!(new=malloc( strlen(avline)+5)))
  1668.         ierror( NULL, 512 );
  1669.     else {
  1670.         new->next=NULL;
  1671.         strcpy( new->name,avline );
  1672.         if( CRoot )
  1673.             LastCRoot->next=new;
  1674.         else 
  1675.             CRoot=new;
  1676.         LastCRoot=new;
  1677.     }
  1678.     return 0;
  1679. }
  1680.  
  1681. do_getcl( void )
  1682. {
  1683.     char *s=getclass(av[1]);
  1684.     if( s ) printf("%s\n",s);
  1685.     return 0;
  1686. }
  1687.  
  1688. do_action( char *argline )
  1689. {
  1690.     char *args, err;
  1691.     int abort=options&1;
  1692.  
  1693.     args=compile_av( av,3,ac,' ',0 );
  1694.     err=doaction(av[2],av[1],args);
  1695.     if( !abort )
  1696.         if( err==9 )     ierror(av[2], 205 );
  1697.         else if(err==10) fprintf(stderr,"Can't identify %s\n", av[2] );
  1698.         else if(err==11) fprintf(stderr,"Can't '%s' this file\n",av[1] );
  1699.         else if(err==12) fprintf(stderr,"Error executing the program to '%s' this file\n",av[1] );
  1700.     free(args);
  1701.     return abort ? !err : err;
  1702. }
  1703.  
  1704.  
  1705. #if 0
  1706. static void
  1707. viewfile( FILE *fi )
  1708. {
  1709.     char buf[256];
  1710.     long pages[64];
  1711.  
  1712.     xxxyyy
  1713.  
  1714. }
  1715.  
  1716. do_more( void )
  1717. {
  1718.     FILE *fi;
  1719.     int i;
  1720.  
  1721.     if( ac==1 && !IsInteractive(Input()))
  1722.         viewfile(stdin);
  1723.     else 
  1724.         for( i=1; i<ac && !breackcheck(); i++ ) {
  1725.             if( fi=fopen( av[i], "r" ))
  1726.                 viewfile( fi ), fclose( fi );
  1727.             else 
  1728.                 fprintf( stderr, "Can't open %s\n" );
  1729. }
  1730. #endif
  1731.